package com.happyhome.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.happyhome.constants.AppConstant;
import com.happyhome.datamodel.CavasObject;
import com.happyhome.datamodel.District;
import com.happyhome.datamodel.House;
import com.happyhome.datamodel.Image;
import com.happyhome.datamodel.News;
import com.happyhome.datamodel.Opinion;
import com.happyhome.datamodel.Parameter;
import com.happyhome.datamodel.Room;
import com.happyhome.datamodel.Utility;
import com.happyhome.services.DistrictService;
import com.happyhome.services.HouseService;
import com.happyhome.services.ImageService;
import com.happyhome.services.NewsService;
import com.happyhome.services.OpinionService;
import com.happyhome.services.ParameterService;
import com.happyhome.services.RoomService;
import com.happyhome.services.UsersService;
import com.happyhome.services.UtilityService;

@Controller
@RequestMapping("/")
public class IndexController {
	
	private static final Logger log = LoggerFactory.getLogger(IndexController.class);
	
	@Autowired
	private HouseService houseService;
	
	@Autowired
	private RoomService roomService;
	
	@Autowired
	private NewsService newsService;
	
	@Autowired
	private ImageService imageService;
	
	@Autowired
	private ParameterService parameterService;
	
	@Autowired
	private OpinionService opinionService;
	
	@Autowired
	private UtilityService utilityService;
	
	@Autowired
	private UsersService usersService;

	@Autowired
	private DistrictService districtService;
	
	@Autowired
	private ServletContext context;
	
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public ModelAndView getdata() {
		
		// load data for index page
		List<Room> listNewestRooms = roomService
				.getRoomsData(AppConstant.LIMIT);
		List<Opinion> listOpinion = opinionService.getOpinionDisplay();
		ModelAndView model = new ModelAndView("index");
		
		// response cavas object to client
		model.addObject("listCavas", getListObjectCavas());
		model.addObject("listOpinion", listOpinion);
		
		// add data to model
		model.addObject("listNewestRooms", listNewestRooms);
		// get all list district 
		List<District> listDistricts = districtService.getAllDistricts();
		model.addObject("listDistricts", listDistricts);
		return model;
	}
	
	@RequestMapping("/productDetail")
	public ModelAndView productDetail(HttpServletRequest request) {
		Long aId = null;
		String type = null;
		House house = null;
		Room room = null;
		News news = null;
		List<Image> listImages = null;
		if(request.getParameter("aId") != null){
			aId = Long.parseLong(request.getParameter("aId"));
		}
		if(request.getParameter("type") != null){
			type = request.getParameter("type");
		}
		if(type != null && aId != null){
			if(type.equals(AppConstant.HOUSES_CODE)){
				house = houseService.findHouseById(aId);
			}else if(type.equals(AppConstant.ROOMS_CODE)){
				room = roomService.findRoomById(aId);
			}else{
				news = newsService.findNesById(aId);
			}
		}
		
		ModelAndView modelAndView = new ModelAndView("aDetail");
		if(house != null){
			modelAndView.addObject("house", house);
			List<Utility> amenities = utilityService.getAllUtilitiesByAId(house.getIdHouse());
			listImages = imageService.getListImageByAId(aId, type);
			for(Image image: listImages){
				image.setUrl("/picture/"+ image.getId());
			}
			modelAndView.addObject("amenities", amenities);
			// get all room of that house
			List<Room> listRooms = roomService.getListRoomsByHouseId(house.getIdHouse(), AppConstant.LIMIT.intValue());
			for(Room tempRoom : listRooms){
				// get image is checked to display on cavas
				Image image = imageService.getImageByAIdIsDisplay(tempRoom.getIdRoom(), AppConstant.ROOMS_CODE);
				if(image == null){
					// get the last newest house
					image = imageService.getImageNewestAId(tempRoom.getIdRoom(), AppConstant.ROOMS_CODE);
				}
				if(image != null){
					tempRoom.setUrl("/picture/"+ image.getId());
				}
				if(house != null){
					tempRoom.setHomeValue(house.getNameHouse());
					tempRoom.setAddress(house.getAddress());
				}
			}
			modelAndView.addObject("listRooms", listRooms);
		}
		
		if(room != null){
			room.setGoogleMap(houseService.getGoogleMap(room.getIdRoom()));
			modelAndView.addObject("room", room);
			List<Utility> amenities = utilityService.getAllUtilitiesByAId(room.getIdRoom());
			listImages = imageService.getListImageByAId(aId, type);
			for(Image image: listImages){
				image.setUrl("/picture/"+ image.getId());
			}
			modelAndView.addObject("amenities", amenities);
		}
		
		if(news != null){
			modelAndView.addObject("news", news);
			modelAndView.addObject("listCavas", getListObjectCavas());
		}
		// if house or room is != null
		if(listImages != null){
			modelAndView.addObject("listImages", listImages);
		}
		return modelAndView;
	}
	
	@RequestMapping("/housesInHappyHomes")
	public ModelAndView houseInHappyHomes() {
		ModelAndView modelAndView = new ModelAndView("housesInHappyHomes");
		modelAndView.addObject("listCavas", getListObjectCavas());
		// get all house in system happy homes
		List<House> listHouses = houseService.getAll();
		StringBuffer listHousesInGoogleMap = new StringBuffer("");
		if(listHouses != null && listHouses.size() > 0L){
			// get all images
			int counter = 0;
			for(House house : listHouses){
				// get image is checked to display on cavas
				Image image = imageService.getImageByAIdIsDisplay(house.getIdHouse(), AppConstant.HOUSES_CODE);
				if(image == null){
					// get the last newest house
					image = imageService.getImageNewestAId(house.getIdHouse(), AppConstant.HOUSES_CODE);
				}
				if(image != null){
					house.setUrl("/picture/"+ image.getId());
				}
				house.setUser(houseService.getManagerInformation(house));
				if(usersService.getImageOfManager(house.getIdHouse()) != null){
					house.setManagerUrl("/picture/"+ usersService.getImageOfManager(house.getIdHouse()));
				}
				// get district information
				District district = houseService.getDistrictByHouse(house);
				house.setDistrict(district);
				listHousesInGoogleMap.append(house.getNameHouse());
				listHousesInGoogleMap.append(",");
				listHousesInGoogleMap.append(house.getGoogleMap());
				listHousesInGoogleMap.append(",");
				listHousesInGoogleMap.append(++counter);
				listHousesInGoogleMap.append("]");
			}
			modelAndView.addObject("listHouses", listHouses);
		}
		modelAndView.addObject("listHousesInGoogleMap", listHousesInGoogleMap);
		return modelAndView;
	}
	
	@RequestMapping("/getListRoomsInHouse")
	public ModelAndView getListRoomsInHouse(@RequestParam(value = "idHouse") Long idHouse) {
		ModelAndView modelAndView = new ModelAndView("roominhouse");
		House house = houseService.findHouseById(idHouse);
		if(house != null){
			// get list images of that house
			List<Image> listImages = imageService.getListImageByAId(house.getIdHouse(), AppConstant.HOUSES_CODE);
			if(listImages != null){
				for(Image image : listImages){
					image.setUrl("picture/" + image.getId());
				}
				modelAndView.addObject("listImages", listImages);
			}
			// get list room of that house
			List<Room> listRooms =  roomService.getListRoomsByHouseId(house.getIdHouse(), AppConstant.LIMIT.intValue());
			modelAndView.addObject("listRooms", listRooms);
		}
		List<Opinion> listOpinion = opinionService.getOpinionDisplay();
		modelAndView.addObject("listOpinion", listOpinion);
		return modelAndView;
	}
	
	/**
	 * Set session variable to asynchronize variable
	 * @param request
	 * @return
	 */
	@RequestMapping("/asyncSessionVariable")
	public @ResponseBody String asyncSessionVariable(HttpServletRequest request) {
		String isOpenValue = request.getParameter("isOpen");
		if(isOpenValue != null){
			request.getSession().setAttribute("isOpen", Boolean.valueOf(isOpenValue));
			return isOpenValue;
		}
		return null;
	}
	/**
	 * getListRoomsByDistrict on Menu
	 * @param idDistrict
	 * @return list room in that district
	 */
	@RequestMapping("/getRoomsSearchResult")
	public ModelAndView getRoomsSearchResult(HttpServletRequest request) {
		ModelAndView modelAndView = new ModelAndView("resultSearch");
		Long minCost = null;
		Long maxCost = null;
		List<Long> idDistricts = null;
		if(request.getParameter("minCost") != null){
			minCost = Long.parseLong(request.getParameter("minCost"));
		}
		if(request.getParameter("maxCost") != null){
			maxCost = Long.parseLong(request.getParameter("maxCost"));
		}
		if(request.getParameter("idDistricts") != null){
			String idsString = request.getParameter("idDistricts");
			String[] ids = idsString.split(",");
			idDistricts = new ArrayList<Long>();
			for(String id : ids){
				idDistricts.add(Long.parseLong(id));
			}
		}
		List<Room> listRooms = roomService.getListRoomByDistrict(idDistricts, minCost, maxCost, AppConstant.LIMIT);
		List<Opinion> listOpinion = opinionService.getOpinionDisplay();
		modelAndView.addObject("listOpinion", listOpinion);
		modelAndView.addObject("listRooms", listRooms);
		modelAndView.addObject("listCavas", getListObjectCavas());
		return modelAndView;
	}
	
	@RequestMapping(value = "/picture/{id}", method = RequestMethod.GET)
    public void picture(HttpServletResponse response, @PathVariable Long id) {
        Image image = imageService.getImageById(id);
        String pathname = context.getRealPath(AppConstant.IMAGE_LOCATION);
        File imageFile = new File(pathname + "/"+ image.getNewFilename());
        response.setContentType(image.getContentType());
        response.setContentLength(image.getSize().intValue());
        try {
            InputStream is = new FileInputStream(imageFile);
            IOUtils.copy(is, response.getOutputStream());
        } catch(IOException e) {
            log.error("Could not show picture "+id, e);
        }
    }
    
    @RequestMapping(value = "/thumbnail/{id}", method = RequestMethod.GET)
    public void thumbnail(HttpServletResponse response, @PathVariable Long id) {
        Image image = imageService.getImageById(id);
        String pathname = context.getRealPath(AppConstant.IMAGE_LOCATION);
        File imageFile = new File(pathname + "/" + image.getThumbnailFilename());
        response.setContentType(image.getContentType());
        response.setContentLength(image.getThumbnailSize().intValue());
        if(imageFile.exists()){
	        try {
	            InputStream is = new FileInputStream(imageFile);
	            IOUtils.copy(is, response.getOutputStream());
	        } catch(IOException e) {
	            log.error("Could not show thumbnail "+id, e);
	        }
        }
    }
    
    private List<CavasObject> getListObjectCavas(){
    	// list result response to client
		List<CavasObject> listCavas = new ArrayList<CavasObject>();
		// load order item to display cavas
		Parameter houseParameter = parameterService.getParameterByCode(AppConstant.HOUSES_CODE);
		Parameter roomParameter = parameterService.getParameterByCode(AppConstant.ROOMS_CODE);
		Parameter newsParameter = parameterService.getParameterByCode(AppConstant.NEWS_CODE);
		
		// init list house, room, news
		List<House> listHouses = null;
		List<Room> listRooms = null;
		List<News> listNews = null;
		
		// load number items
		if(houseParameter != null && houseParameter.getValue() > 0L){
			listHouses = houseService.getListHousesIsDisplay();
			// get all images
			for(House house : listHouses){
				// get image is checked to display on cavas
				Image image = imageService.getImageByAIdIsDisplay(house.getIdHouse(), AppConstant.HOUSES_CODE);
				if(image == null){
					// get the last newest house
					image = imageService.getImageNewestAId(house.getIdHouse(), AppConstant.HOUSES_CODE);
				}
				if(image != null){
					house.setUrl("/picture/"+ image.getId());
				}
			}
		}
		if(roomParameter != null && roomParameter.getValue() > 0L){
			listRooms = roomService.getListRoomsIsDisplay();
			// get all images
			for(Room room : listRooms){
				// get image is checked to display on cavas
				Image image = imageService.getImageByAIdIsDisplay(room.getIdRoom(), AppConstant.ROOMS_CODE);
				if(image == null){
					// get the last newest house
					image = imageService.getImageNewestAId(room.getIdRoom(), AppConstant.ROOMS_CODE);
				}
				if(image != null){
					room.setUrl("/picture/"+ image.getId());
				}
			}
		}
		if(newsParameter != null && newsParameter.getValue() > 0L){
			listNews = newsService.getListNewsIsDisplay();
			for(News news : listNews){
				// get image is checked to display on cavas
				news.setThumbnailUrl("/picture/"+ news.getImageThumbnail().getId());
			}
		}
		
		if(listHouses == null && listRooms == null && listNews == null){
			listHouses = houseService.getListHousesNewestLimit(AppConstant.LIMIT_CAVAS_NUMBER);
			// get all images
			for(House house : listHouses){
				// get image is checked to display on cavas
				Image image = imageService.getImageByAIdIsDisplay(house.getIdHouse(), AppConstant.HOUSES_CODE);
				if(image == null){
					// get the last newest house
					image = imageService.getImageNewestAId(house.getIdHouse(), AppConstant.HOUSES_CODE);
				}
				if(image != null){
					house.setUrl("/picture/"+ image.getId());
				}
			}
		}
    			
    	List<Long> listOrder = new ArrayList<Long>();
		if(listHouses != null && listHouses.size() > 0){
			listOrder.add(houseParameter.getOrder());
		}
		if(listNews != null && listNews.size() > 0 ){
			listOrder.add(newsParameter.getOrder());
		}
		if(listRooms != null && listRooms.size() > 0 ){
			listOrder.add(roomParameter.getOrder());
		}
		
		Long temp;
		for(int counter = 0; counter < listOrder.size() - 1; counter++){
			for(int index = 0; index < listOrder.size() - 1 - counter; index++){
				if(listOrder.get(index) > listOrder.get(index + 1)){
					temp = listOrder.get(index);
					listOrder.set(index, listOrder.get(index + 1));
					listOrder.set(index + 1, temp);
				}
			}
		}
    	for(int i = 0; i < listOrder.size(); i++){
			if(listOrder.get(i) == houseParameter.getOrder()){
				for(House house : listHouses){
					CavasObject cavas = new CavasObject();
					cavas.setId(house.getIdHouse());
					cavas.setName(house.getNameHouse());
					cavas.setUrl(house.getUrl());
					cavas.setType(AppConstant.HOUSES_CODE);
					listCavas.add(cavas);
				}
			}
			if(listOrder.get(i) == roomParameter.getOrder()){
				for(Room room : listRooms){
					CavasObject cavas = new CavasObject();
					cavas.setId(room.getIdRoom());
					cavas.setName(room.getNameRoom());
					cavas.setUrl(room.getUrl());
					cavas.setType(AppConstant.ROOMS_CODE);
					listCavas.add(cavas);
				}
			}
			if(listOrder.get(i) == newsParameter.getOrder()){
				for(News news : listNews){
					CavasObject cavas = new CavasObject();
					cavas.setId(news.getIdNews());
					cavas.setName(news.getTitleNews());
					cavas.setUrl(news.getThumbnailUrl());
					cavas.setType(AppConstant.NEWS_CODE);
					listCavas.add(cavas);
				}
			}
		}
    	return listCavas;
    }
}
